package org.example.structure.flyweight;

/**
 * 类描述：String类的测试
 * <br>
 *
 * @author ZS
 * @version 1.0
 * @date 2020/12/30
 **/
public class StringDemo {
    public static void main(String[] args) {
        // JVM在编译期间就将"Hello"字面量放到字符串常量池
        // 在java启动的时候就已经加载到内存中，所以s1执行的是常量池中的引用
        String s1 = "Hello";
        // s2指向的字面量在常量池中已经存在，返回字面量的引用
        String s2 = "Hello";
        // 字面量的拼接，JVM在编译期间会进行优化，所以
        String s3 = "He" + "llo";

        // new String("lo") 生成了两个对象：字符串常量池中的字面量"lo" 和 new String("lo") 存在于堆中
        // String s4 = "hel" + new String("lo") 实质上是两个对象的相加，编译器不会进行优化，相加的结果存在于堆中，而s1存在于字符串常量池中，当然不相等
        String s4 = "hel" + new String("lo");

        // 由于字面量 Hello 已经存在字符串常量池，因此new String("Hello")只在堆中创建了一个对象
        String s5 = new String("Hello");

        // s5.intern()一个位于堆中的字符串在运行期间动态地加入字符串常量池（字符串常量池的内容是在程序启动的时候就已经加载好了的）
        // 如果字符串常量池中有该对象对应的字面量，则返回该字面量在字符串常量池中的引用；否则，复制一份该字面量到字符串常量池并返回它的引用
        String s6 = s5.intern();

        String s7 = "H";
        String s8 = "ello";
        // 是指是两个对象的相加，编译器不会优化，相加的结果位于堆中
        String s9 = s7 + s8;

        System.out.println(s1 == s2); // true
        System.out.println(s1 == s3); // true
        System.out.println(s1 == s4); // false
        System.out.println(s1 == s6); // true
        System.out.println(s1 == s9); // false
    }
}
